﻿using System;
using System.Reflection.PortableExecutable;
using System.IO;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace ConsoleApp5
{
    class Program
    {
        /// <summary>
        /// 解析PE文件
        /// </summary>
        /// <param name="filename">文件路径</param>
        static void ParsePeFile(string filename)
        {
            PeParse peParse;
            try
            {
                // 花里胡哨的转换，它还真能解析出来 FileStream => PEReader => PeParse 
                peParse = new(new(File.OpenRead(filename)));
            }
            catch (IOException fileException)
            {
                Console.WriteLine($"{fileException.Message}");
                return;
            }

            // 枚举导入表
            foreach (ImportDescriptor descriptor in peParse.ParseImportDescriptor())
            {
                string data = peParse.ParseCharVector(descriptor.Name);
                Console.WriteLine($"Dll name : {data}");

                // 枚举每个导入表中的Thunk
                BlobReader thunkDataReader = peParse.GetRvaBlob(descriptor.OriginalFirstThunk);
                foreach (ThunkData thunk in peParse.ParseThunkData(thunkDataReader))
                {
                    // Ordinal 导入
                    if ((thunk.ForwarderString & int.MinValue) != 0)
                    {
                        Console.WriteLine($"\tOrdinal: {thunk.ForwarderString & short.MaxValue}");
                    }
                    else // 名称导入
                    {
                        BlobReader importByNameReader = peParse.GetRvaBlob(thunk.ForwarderString);
                        ImportByName importByName = peParse.ParseImportByName(importByNameReader);
                        Console.WriteLine($"\tName: {importByName.Name}");
                    }
                }
            }
        }
        static void Main(string[] args)
        {
            if (args.Length > 0)
                ParsePeFile(args[0]);
            else
                Console.WriteLine($"use {Process.GetCurrentProcess().MainModule.FileName} <文件路径>");
        }
    }
}
